package com.theaf.basemodule.service.impl;

import com.theaf.basemodule.common.api.AreaService;
import com.theaf.basemodule.common.condition.AreaCondition;
import com.theaf.basemodule.common.dto.AreaDTO;
import com.theaf.basemodule.common.model.SysArea;
import com.theaf.basemodule.common.vo.AreaVO;
import com.theaf.basemodule.dao.AreaDAO;
import com.theaf.core.repo.kit.SimpleSortBuilder;
import com.theaf.core.repo.specification.SqlBuilder;
import com.theaf.core.repo.specification.SqlOperator;
import com.theaf.core.repo.specification.SqlValue;
import com.theaf.core.utils.BeanMapper;
import com.theaf.core.utils.DictionaryHelper;
import com.theaf.core.utils.SmExceptionHelper;
import com.theaf.core.utils.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @Author:songwenke
 * @Description:地区服务
 * @Date:create in 16:28 2018/2/11
 * @Modified By:
 **/
@Service
public class AreaServiceImpl implements AreaService {
    @Autowired
    private AreaDAO areaDAO;
    @Override
    public AreaDTO findById(Long id) {
        if(id==null){
            return null;
        }
        return AreaDTO.fromPo(areaDAO.findOne(id));
    }

    @Override
    public List<AreaDTO> findDirecdChild(Long id) {
        List<SysArea> sysAreas = areaDAO.findAll(SqlBuilder.start("pid",
                id==null? SqlOperator.OPER.NULL: SqlOperator.OPER.EQ,id).gen());
        List<AreaDTO> areaDTOS = new ArrayList();
        sysAreas.forEach((SysArea sysArea)->{
            areaDTOS.add(AreaDTO.fromPo(sysArea));
        });
        return areaDTOS;
    }

    @Override
    public List<AreaDTO> findChild(Long id) {
        List<SysArea> sysAreas = null;
        if(id==null){
            sysAreas = areaDAO.findAll();
        }else {
            sysAreas = areaDAO.findAll(
                    SqlBuilder.start("levelCode", SqlOperator.OPER.LIKER,
                            areaDAO.subquery(SqlBuilder.start("id", id).
                                    setSelects(new String[]{"levelCode"}))).gen());
        }
        List<AreaDTO> areaDTOS = new ArrayList();
        sysAreas.forEach((SysArea sysArea)->{
            areaDTOS.add(AreaDTO.fromPo(sysArea));
        });
        return areaDTOS;
    }



    @Override
    public Long save(AreaVO areaVO) {
        SysArea sysArea = BeanMapper.map(areaVO,SysArea.class);
        if(areaVO.getPid()!=null) {
            sysArea.setParent(new SysArea());
            sysArea.getParent().setId(areaVO.getPid());
        }
        areaDAO.initLevel(sysArea,"levelCode","id","parent.id");
        areaDAO.save(sysArea);
        return sysArea.getId();
    }

    @Override
    public void delete(Long id) {
        SysArea sysArea = areaDAO.findOne(id);
        if(areaDAO.count(SqlBuilder.start("parent.id",id).gen())>0){
            throw SmExceptionHelper.sysCheckException("\""+sysArea.getName()+"\"存在子地区，不能删除");
        }
        areaDAO.delete(id);
    }

    /**
     * 查询地区指定类型的上级对象
     * @param id
     * @param type 支付模糊匹配
     * @return
     */
    @Override
    public AreaDTO findParentByType(Long id, String type) {
        List<SysArea> sysAreas = areaDAO.findAll(
                SqlBuilder.start(areaDAO.subquery(SqlBuilder.start("id", id).
                                setSelects(new String[]{"levelCode"})), SqlOperator.OPER.LIKER,
                        "levelCode").and("type", SqlOperator.OPER.LIKER,SqlValue.parse(type)).gen());
        AreaDTO areaDTO = null;
        for(SysArea sysArea:sysAreas){
            areaDTO = AreaDTO.fromPo(sysArea);
            break;
        };
        return areaDTO;
    }

    @Override
    public String getFullNameById(Long id) {
        List<SysArea> sysAreas = areaDAO.findAll(
                SqlBuilder.start(areaDAO.subquery(SqlBuilder.start("id", id).
                                setSelects(new String[]{"levelCode"})), SqlOperator.OPER.LIKER,
                        "levelCode").gen(), SimpleSortBuilder.generateSort("levelCode"));
        String fullName = "";
        for(SysArea sysArea:sysAreas){
            fullName+=sysArea.getName()+
                    DictionaryHelper.getChlidMemo(AreaService.TYPE_DIC_NAME,sysArea.getType());
        };
        return fullName;
    }

    @Override
    public List<AreaDTO> findArea(AreaCondition condition) {
        List<SysArea> sysAreas = null;
        SqlBuilder sqlbuilder = new SqlBuilder();
        if(StringUtils.isNotEmpty(condition.getName())||StringUtils.isNotEmpty(condition.getType())) {
            sqlbuilder.and(areaDAO.subquery(
                    SqlBuilder.start("name", SqlOperator.OPER.LIKE, SqlValue.parse(condition.getName()))
                            .and("type", SqlValue.parse(condition.getType()))
                            .and("levelCode", SqlOperator.OPER.LIKER,"@levelCode")
                            .setSelects(new String[]{"levelCode"})), SqlOperator.OPER.EXISTS, null);
        }
        if(StringUtils.isNotEmpty(condition.getTopName())){
            sqlbuilder.and("levelCode",SqlOperator.OPER.LIKER,areaDAO.subquery(
                    SqlBuilder.start("name",SqlValue.parse(condition.getTopName()))
                            .setSelects(new String[]{"levelCode"})));
        }
        if(condition.getFilterId()!=null){
            sqlbuilder.and("levelCode",SqlOperator.OPER.NLIKER,areaDAO.subquery(
                    SqlBuilder.start("id",condition.getFilterId())
                            .setSelects(new String[]{"levelCode"})));
        }
        sysAreas = areaDAO.findAll(sqlbuilder.gen());
        return (List<AreaDTO>)sysAreas.parallelStream().
                map(n->AreaDTO.fromPo((SysArea) n)).collect(Collectors.toList());
    }
}
